package com.zxy.ziems.server.device.modules.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.toolkit.reflect.SpringReflectionHelper;
import com.zxy.btp.common.util.JsonUtils;
import com.zxy.ziems.server.device.modules.DeviceChannelProcessor;
import com.zxy.ziems.server.device.pojo.bo.Triplet;
import com.zxy.ziems.server.utils.AssertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;

/**
 * 通道高级配置
 * @author 10348359
 * @create 2024-04-25 23:03
 */
@Slf4j
@Service
public class DeviceChannelProcessorManager implements ApplicationListener<ApplicationReadyEvent> {

     public <R> void doProcessDecodeAdvancedConfigIfPresentBy(String protocol, String advanced, BiConsumer<? super DeviceChannelProcessor, R> action) {
        if (Objects.isNull(action)) {
            return;
        }
        if (StrUtil.isBlank(advanced)) {
            return;
        }
        Triplet<Class<?>, Class<?>, DeviceChannelProcessor> pair = processorMap.get(protocol);
        if (Objects.isNull(pair)) {
            return;
        }
        R config = (R) JsonUtils.parseObject(advanced, pair.getSecond());
        action.accept(pair.getThird(), config);
    }

    public  void doProcessAdvancedConfigIfPresentBy(String protocol, Object advanced, BiConsumer<? super DeviceChannelProcessor, Object> action) {
        if (Objects.isNull(advanced)) {
            return;
        }

        if (Objects.isNull(action)) {
            return;
        }

        Triplet<Class<?>, Class<?>, DeviceChannelProcessor> pair = processorMap.get(protocol);
        if (Objects.isNull(pair)) {
            return;
        }
        Object newExtra = JsonUtils.parseObject(JsonUtils.toJSONString(advanced), pair.getFirst());
        AssertUtil.nonNull(newExtra, "[通信通道]高级配置:{}序列化出错", advanced);

        action.accept(pair.getThird(), newExtra);
    }

    private Map<String, Triplet<Class<?>, Class<?>, DeviceChannelProcessor>> processorMap = new HashMap<>(0);

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        Map<String, DeviceChannelProcessor> beansOfType = SpringUtil.getBeansOfType(DeviceChannelProcessor.class);
        beansOfType.forEach((key, processor) -> {
            String protocol = processor.supportProtocol();
            if (Objects.isNull(protocol)) {
                return;
            }
            if (processorMap.containsKey(protocol)) {
                log.error("[通信通道]协议：{}重复处理", protocol);
                return;
            }
            Class<?>[] typeArguments = SpringReflectionHelper.resolveTypeArguments(processor.getClass(), DeviceChannelProcessor.class);
            if (null == typeArguments || typeArguments.length < 2) {
                return;
            }
            Triplet<Class<?>, Class<?>, DeviceChannelProcessor> p = Triplet.of(typeArguments[0], typeArguments[1], processor);
            processorMap.put(protocol, p);
        });
    }
}
